#-*- coding: utf-8 -*-

'''
autor1: João Reis, Nº5236
autor2: Miguel Romão, Nº5513
data: 2 de Novembro 2013
obs: Pesquisas sobre a base de dados
'''

from criar_bd import Tabela_Dados, Tabela_Distritos, Tabela_Institutos
from sqlalchemy import *
from sqlalchemy.sql import select
from sqlalchemy.orm import sessionmaker

class Pesquisas:
	'''
		Esta classe contém as funções de pesquisa das estatísticas pedidas.
	'''

	def __init__(self):
		self.base_dados = create_engine('sqlite:///base_dados/sql_lp_1314.db', 
			echo=False)
		Session = sessionmaker(bind = self.base_dados)
		self.sessao = Session()

	def estatistica_1(self):
		'''
			Função que calcula o número de alunos colocados por instituição.

			Returns:
					uma lista de grupos compostos por código da instituição, 
					nome da instituição	e o número de alunos colocados nessa instituição.
		'''

		# query para ir buscar os codigos das instituicoes
		query1 = select([Tabela_Dados.Codigo_da_Instituicao])
		resultado1 = self.sessao.execute(query1)

		lista_instituicoes = []

		for nome in resultado1:
			lista_instituicoes.append(nome[0])

		# elimina as repeticoes dos codigos e ordena-os
		lista_inst_ordenada = sorted(set(lista_instituicoes))

		# lista de grupos [instituto, nome do instituto, numero de colocados]
		lista_inst_col = []

		for numero in lista_inst_ordenada:
			lista_temp = [] # lista de colocados temporária
			lista_nomes_inst_temp = [] # lista de nomes dos institutos temporária
			lista_inst_col_temp = [] # lista de grupos [numero, instituto, colocados] temporária
			
			# query para ir buscar o nome da instituicao consoante o numero da mesma
			query2 = select([Tabela_Dados.Nome_da_Instituicao], 
				Tabela_Dados.Codigo_da_Instituicao == numero)
			resultado2 = self.sessao.execute(query2)

			for linha in resultado2:
				lista_nomes_inst_temp.append(linha[0])
			lista_nomes_inst = sorted(set(lista_nomes_inst_temp))

			# query para ir buscar os colocados consoante o codigo da instituicao			
			query3 = select([Tabela_Dados.Colocados], 
				Tabela_Dados.Codigo_da_Instituicao == numero)
			resultado3 = self.sessao.execute(query3)
			
			for linha in resultado3:
				for x in xrange(len(linha)):
					lista_temp.append(int(linha[x]))
			
			total_colocados = sum(lista_temp) # soma o total de colocados para aquela instituicao
			lista_inst_col_temp.extend([numero, lista_nomes_inst[0].encode('utf-8'), 
				total_colocados])
			lista_inst_col.append(lista_inst_col_temp)
			
			del lista_temp, total_colocados, lista_inst_col_temp, lista_nomes_inst

		return lista_inst_col
		
	
	def estatistica_2(self):
		'''
			Função que calcula o número de alunos colocados por distrito.

			Returns:
					uma lista de pares compostos por nome do distrito e o número 
					de alunos colocados por distrito.
		'''

		# query para ir buscar os nomes dos distritos
		query1 = select([Tabela_Distritos.nome_do_distrito])
		resultado1 = self.sessao.execute(query1)

		lista_distritos = []
		lista_dist_colocados = []

		for nome in resultado1:
			lista_distritos.append(nome[0])

		for distrito in lista_distritos:
			# Query para ir buscar os nomes dos institutos de um
			# determinado distrito
			query2 = select([Tabela_Institutos.nome_do_instituto], 
				Tabela_Institutos.nome_do_distrito == distrito)
			resultado2 = self.sessao.execute(query2)

			total_col_dist_temp = [] # lista temporária de colocados por distrito
			lista_dist_col_temp = []

			for nome in resultado2:
				numero_colocados = []
				# query para ir buscar o número de colocados por instituto
				query3 = select([Tabela_Dados.Colocados], 
					Tabela_Dados.Nome_da_Instituicao.contains(nome[0]))
				resultado3 = self.sessao.execute(query3)

				for linha in resultado3:
					for x in xrange(len(linha)):
						numero_colocados.append(int(linha[x]))

				total_col_dist_temp.append(sum(numero_colocados))

				del numero_colocados

			total_col_dist = sum(total_col_dist_temp)
			lista_dist_col_temp.extend([distrito.encode('utf-8'), total_col_dist])
			lista_dist_colocados.append(lista_dist_col_temp)

			del total_col_dist, lista_dist_col_temp, total_col_dist_temp

		return lista_dist_colocados
		
	def estatistica_3(self):
		'''
			Função que calcula a permilagem de alunos colocados por distrito.

			Returns:
					uma lista de pares compostos por nome do distrito e 
					permilagem dos alunos colocados por distrito.
		'''

		# query para ir buscar os nomes dos distritos
		query1 = select([Tabela_Distritos.nome_do_distrito])
		resultado1 = self.sessao.execute(query1)

		lista_distritos = []
		lista_permilagem = []

		for nome in resultado1:
			lista_distritos.append(nome[0])

		lista_total_col_temp = [] # lista temporária para o total de colocados

		# query para ir buscar o total de colocados
		query4 = select([Tabela_Dados.Colocados])
		resultado4 = self.sessao.execute(query4)

		for numero in resultado4:
			lista_total_col_temp.append(numero[0])

		total_col = sum(lista_total_col_temp) # total de colocados

		for distrito in lista_distritos:
			# Query para ir buscar os nomes dos institutos de um
			# determinado distrito
			query2 = select([Tabela_Institutos.nome_do_instituto], 
				Tabela_Institutos.nome_do_distrito == distrito)
			resultado2 = self.sessao.execute(query2)

			total_col_dist_temp = [] # lista temporária de colocados por distrito
			lista_dist_col_temp = []

			for nome in resultado2:
				numero_colocados = []
				# query para ir buscar o número de colocados por instituto
				query3 = select([Tabela_Dados.Colocados], 
					Tabela_Dados.Nome_da_Instituicao.contains(nome[0]))
				resultado3 = self.sessao.execute(query3)

				for linha in resultado3:
					for x in xrange(len(linha)):
						numero_colocados.append(float(linha[x]))

				total_col_dist_temp.append(sum(numero_colocados))

				del numero_colocados

			total_col_dist = (sum(total_col_dist_temp)/total_col)*1000
			lista_dist_col_temp.extend([distrito.encode('utf-8'), total_col_dist])
			lista_permilagem.append(lista_dist_col_temp)

			del total_col_dist, lista_dist_col_temp, total_col_dist_temp

		return lista_permilagem
		
	def estatistica_4(self):
		'''
			Função que calcula a percentagem de alunos colocados por instituição.

			Returns:
					uma lista de grupos compostos por nome da instituição
					e a percentagem de alunos colocados por instituição.
		'''
		
		# query para ir buscar os codigos das instituicoes
		query1 = select([Tabela_Dados.Codigo_da_Instituicao])
		resultado1 = self.sessao.execute(query1)

		lista_instituicoes = []

		for nome in resultado1:
			lista_instituicoes.append(nome[0])

		# elimina as repeticoes dos codigos e ordena-os
		lista_inst_ordenada = sorted(set(lista_instituicoes))

		lista_total_col_temp = [] # lista temporária para o total de colocados
		
		# query para ir buscar o total de colocados
		query4 = select([Tabela_Dados.Colocados])
		resultado4 = self.sessao.execute(query4)

		for numero in resultado4:
			lista_total_col_temp.append(numero[0])

		total_col = sum(lista_total_col_temp) # total de colocados

		# lista de grupos [nome do instituto, percentagem de colocados]
		lista_inst_percentagem = []

		for numero in lista_inst_ordenada:
			lista_temp = [] # lista de colocados temporária
			lista_nomes_inst_temp = [] # lista de nomes dos institutos temporária
			lista_inst_percentagem_temp = [] # lista de pares [instituto, colocados] temporária
			
			# query para ir buscar o nome da instituicao consoante o numero da mesma
			query2 = select([Tabela_Dados.Nome_da_Instituicao], 
				Tabela_Dados.Codigo_da_Instituicao == numero)
			resultado2 = self.sessao.execute(query2)

			for linha in resultado2:
				lista_nomes_inst_temp.append(linha[0])
			lista_nomes_inst = sorted(set(lista_nomes_inst_temp))

			# query para ir buscar os colocados consoante o codigo da instituicao			
			query3 = select([Tabela_Dados.Colocados], 
				Tabela_Dados.Codigo_da_Instituicao == numero)
			resultado3 = self.sessao.execute(query3)
			
			for linha in resultado3:
				for x in xrange(len(linha)):
					lista_temp.append(float(linha[x]))
			
			# soma o total de colocados para aquela instituicao
			total_colocados = (sum(lista_temp)/total_col)*100

			lista_inst_percentagem_temp.extend([lista_nomes_inst[0].encode('utf-8'), 
				total_colocados])
			lista_inst_percentagem.append(lista_inst_percentagem_temp)
			
			del lista_temp, total_colocados, lista_inst_percentagem_temp, lista_nomes_inst

		return lista_inst_percentagem
	
	def estatistica_5(self):
		'''
			Função que calcula o número de vagas por colocar por instituição.

			Returns:
					uma lista de grupos compostos por código da instituição, 
					nome da instituição e o número de vagas por colocar por instituição.
		'''

		# query para ir buscar os codigos das instituicoes
		query1 = select([Tabela_Dados.Codigo_da_Instituicao])
		resultado1 = self.sessao.execute(query1)

		lista_instituicoes = []

		for nome in resultado1:
			lista_instituicoes.append(nome[0])

		# elimina as repeticoes dos codigos e ordena-os
		lista_inst_ordenada = sorted(set(lista_instituicoes))

		# lista de grupos [numero da instituicao, nome da instituicao, numero de vagas]
		lista_inst_vagas = []

		for numero in lista_inst_ordenada:
			lista_temp = [] # lista de vagas temporária
			lista_nomes_inst_temp = [] # lista de nomes dos institutos temporária
			lista_inst_vagas_temp = [] # lista de grupos [numero, instituto, vagas] temporária
			
			# query para ir buscar o nome da instituicao consoante o numero da mesma
			query2 = select([Tabela_Dados.Nome_da_Instituicao], 
				Tabela_Dados.Codigo_da_Instituicao == numero)
			resultado2 = self.sessao.execute(query2)

			for linha in resultado2:
				lista_nomes_inst_temp.append(linha[0])
			lista_nomes_inst = sorted(set(lista_nomes_inst_temp))

			# query para ir buscar as vagas consoante o codigo da instituicao			
			query3 = select([Tabela_Dados.Vagas_Sobrantes], 
				Tabela_Dados.Codigo_da_Instituicao == numero)
			resultado3 = self.sessao.execute(query3)
			
			for linha in resultado3:
				for x in xrange(len(linha)):
					lista_temp.append(int(linha[x]))
			
			total_vagas = sum(lista_temp) # soma o total de vagas para aquela instituicao
			lista_inst_vagas_temp.extend([numero, lista_nomes_inst[0].encode('utf-8'), 
				total_vagas])
			lista_inst_vagas.append(lista_inst_vagas_temp)
			
			del lista_temp, total_vagas, lista_inst_vagas_temp, lista_nomes_inst
			
		return lista_inst_vagas
		
	def estatistica_6(self):
		'''
			Função que calcula o número de vagas por colocar por distrito.

			Returns:
					uma lista de pares compostos por nome do distrito e número 
					de vagas sobrantes por distrito.
		'''

		# query para ir buscar os nomes dos distritos
		query1 = select([Tabela_Distritos.nome_do_distrito])
		resultado1 = self.sessao.execute(query1)

		lista_distritos = []
		lista_dist_vagas = []

		for nome in resultado1:
			lista_distritos.append(nome[0])

		for distrito in lista_distritos:
			# Query para ir buscar os nomes dos institutos de um determinado distrito
			query2 = select([Tabela_Institutos.nome_do_instituto], 
				Tabela_Institutos.nome_do_distrito == distrito)
			resultado2 = self.sessao.execute(query2)

			total_vagas_dist_temp = [] # lista temporária de vagas por distrito
			lista_dist_vagas_temp = [] # lista temporária de pares [distrito, vagas]

			for nome in resultado2:
				numero_colocados = []
				# query para ir buscar o número de vagas por instituto
				query3 = select([Tabela_Dados.Vagas_Sobrantes], 
					Tabela_Dados.Nome_da_Instituicao.contains(nome[0]))
				resultado3 = self.sessao.execute(query3)

				for linha in resultado3:
					for x in xrange(len(linha)):
						numero_colocados.append(int(linha[x]))

				total_vagas_dist_temp.append(sum(numero_colocados))

				del numero_colocados

			total_vagas_dist = sum(total_vagas_dist_temp)
			lista_dist_vagas_temp.extend([distrito.encode('utf-8'), total_vagas_dist])
			lista_dist_vagas.append(lista_dist_vagas_temp)

			del total_vagas_dist, lista_dist_vagas_temp, total_vagas_dist_temp

		return lista_dist_vagas
